package com.css.fxfzfxqh.modules.buildingIndividual.service.impl;

import cn.afterturn.easypoi.excel.ExcelImportUtil;
import cn.afterturn.easypoi.excel.entity.ImportParams;
import cn.afterturn.easypoi.excel.entity.result.ExcelImportResult;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.IdUtil;
import com.alibaba.fastjson.JSONObject;
import com.css.fxfzfxqh.base.attachment.entity.AttachmentInfoEntity;
import com.css.fxfzfxqh.base.attachment.service.AttachmentInfoService;
import com.css.fxfzfxqh.base.dict.service.DictService;
import com.css.fxfzfxqh.constants.FxfzConstants;
import com.css.fxfzfxqh.constants.YNEnum;
import com.css.fxfzfxqh.modules.buildingIndividual.entity.BuildingIndividualDataVersion;
import com.css.fxfzfxqh.modules.buildingIndividual.entity.BuildingIndividualEntity;
import com.css.fxfzfxqh.modules.buildingIndividual.param.PageQueryParam;
import com.css.fxfzfxqh.modules.buildingIndividual.repository.BuildingIndividualDataVersionRepository;
import com.css.fxfzfxqh.modules.buildingIndividual.repository.BuildingIndividualRepository;
import com.css.fxfzfxqh.modules.buildingIndividual.service.BuildingIndividualDataVersionService;
import com.css.fxfzfxqh.modules.buildingIndividual.verify.VerifyHandler;
import com.css.fxfzfxqh.modules.buildingIndividual.vo.BuildingIndividualDataVersionVO;
import com.css.fxfzfxqh.util.PlatformDateUtils;
import com.css.fxfzfxqh.util.PlatformObjectUtils;
import com.css.fxfzfxqh.util.UUIDGenerator;
import com.css.fxfzfxqh.web.PlatformSessionContext;
import com.css.fxfzfxqh.zcpt.sys.entity.SUser;
import com.css.fxfzfxqh.zcpt.sys.entity.SysUserRole;
import com.css.fxfzfxqh.zcpt.sys.service.SysAreaService;
import com.css.fxfzfxqh.zcpt.sys.service.impl.SUserCacheService;
import com.css.fxfzfxqh.zcpt.sys.service.impl.SysRoleCacheService;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.ValueOperations;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import javax.validation.constraints.NotNull;
import java.io.FileInputStream;
import java.io.InputStream;
import java.net.URLEncoder;
import java.sql.Timestamp;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.time.ZoneOffset;
import java.util.*;
import java.util.stream.Collectors;

/**
 * @Author:
 * @CreateTime: 2024/5/9 11:19
 * @Description:
 */
@Service
public class BuildingIndividualDataVersionServiceImpl implements BuildingIndividualDataVersionService {


    @Resource
    private BuildingIndividualDataVersionRepository buildingIndividualDataVersionRepository;

    @Resource
    private RedisTemplate redisTemplate;

    @Resource
    private SysAreaService sysAreaService;

    @Resource
    private AttachmentInfoService attachmentInfoService;

    @Resource
    private VerifyHandler verifyHandler;

    @Resource
    private SUserCacheService sUserCacheService;

    @Resource
    private DictService dictService;

    @Autowired
    private SysRoleCacheService sysRoleCacheService;

    @Resource
    BuildingIndividualRepository buildingIndividualRepository;


    // 版本号前缀
    public static final String DATA_VERSION_CODE_PREFIX = "JZWDT";

    // 建筑物单体数据版本号流水号redis key
    public static final String DATA_VERSION_CODE_SERIAL_NUMBER_KEY = "fxqh:building_individual:data_version_code:serial_number";


    // 建筑物单体数据建筑物编号流水号redis key
    public static final String JZWBH_CODE_SERIAL_NUMBER_KEY = "fxqh:building_individual:building_code:serial_number";


    @Override
    @Transactional(rollbackFor = Exception.class)
    public Map<String, Object> saveNewVersion(BuildingIndividualDataVersion buildingIndividualDataVersion) throws Exception {
        buildingIndividualDataVersion.setVersionCode(buildIndividualVersionCode(buildingIndividualDataVersion.getDataRangeCountry()));


        this.insertVersionData(buildingIndividualDataVersion);
        Map<String, Object> map = importBuildingIndividualData(buildingIndividualDataVersion.getDataFileIds(), buildingIndividualDataVersion.getVersionCode());
        return map;
    }

    private Map<String, Object> importBuildingIndividualData(String dataFileIds, String dataVersion) throws Exception {
        AttachmentInfoEntity attach = attachmentInfoService.getAttach(dataFileIds);

        String uploadUid = PlatformSessionContext.getUserID();
        ImportParams params = new ImportParams();
        params.setHeadRows(3);
        params.setVerifyHandler(verifyHandler);
        params.setNeedVerify(true);
        boolean res = false;
        Map<String, Object> map = new HashMap<>();

            InputStream inputStream = new FileInputStream(attach.getFileDirId() + attach.getAttachPath());
            ExcelImportResult<BuildingIndividualEntity> result = ExcelImportUtil.importExcelMore(inputStream, BuildingIndividualEntity.class, params);
            List<BuildingIndividualEntity> failList = result.getFailList();
            if (PlatformObjectUtils.isNotEmpty(failList)) {
                StringBuilder errorMsg = new StringBuilder("<font size='4px' color='red'>导入失败,请修改后重新导入</font><br>");
                for (BuildingIndividualEntity buildingIndividualEntity : failList) {
                    errorMsg.append("<font size='4px' ><br>").append("第").append(buildingIndividualEntity.getRowNum() + 1).append("行： ").append(buildingIndividualEntity.getErrorMsg()).append("</font><br>");
                }
                throw new RuntimeException(errorMsg.toString());
            }
            SUser sUser = sUserCacheService.getSUser(uploadUid);
            if (sUser == null) {
                throw new RuntimeException("用户信息查询失败!");
            }
            String userMaxRole = getUserMaxRole(uploadUid);
            StringBuilder userProvinceErrorMsg = new StringBuilder("<font size='4px' color='red'>导入失败,请修改后重新导入</font><br>");
            userProvinceErrorMsg.append("<font size='4px' color='red'>导入失败原因:</font>");
            boolean resFlag = true;
            List<BuildingIndividualEntity> resultData = result.getList();//解析excel
            if (PlatformObjectUtils.isNotEmpty(resultData)) {
                List<BuildingIndividualEntity> list = new ArrayList<>();
                for (BuildingIndividualEntity buildingIndividualEntity : resultData) {
                    buildingIndividualEntity.setId(UUIDGenerator.getUUID());
                    String province = buildingIndividualEntity.getProvince();
                    String city = buildingIndividualEntity.getCity();
                    String county = buildingIndividualEntity.getCounty();
                    String divisionIds = sysAreaService.getIdByCondition(URLEncoder.encode(province, "UTF-8"), URLEncoder.encode(city, "UTF-8"), URLEncoder.encode(county, "UTF-8"));
                    buildingIndividualEntity.setProvinceId(divisionIds.split("_")[0]);
                    buildingIndividualEntity.setCityId(divisionIds.split("_")[1]);
                    buildingIndividualEntity.setCountyId(divisionIds.split("_")[2]);
                    String areaCode = sysAreaService.getDivisionCodeById(divisionIds.split("_")[2]);
                    buildingIndividualEntity.setBuildingCode(getBuildingCode(areaCode.substring(1, areaCode.length() - 1)));
//                    buildingIndividualEntity.setProvinceId("0");
//                    buildingIndividualEntity.setCityId("1");
//                    buildingIndividualEntity.setCountyId("2");
                    if (PlatformObjectUtils.isNotEmpty(userMaxRole) && !userMaxRole.equals("qh_gj_role")) {
                        if (userMaxRole.equals("qh_province_role") && !sUser.getProvinceId().equals(buildingIndividualEntity.getProvinceId())) {
                            resFlag = false;
                            userProvinceErrorMsg.append("<font size='4px' ><br>").append("第").append(buildingIndividualEntity.getRowNum() + 1).append("行").append("的数据省份不是用户所在省份").append("</font><br>");
                            continue;
                        } else if (userMaxRole.equals("qh_city_role") && !sUser.getCityId().equals(buildingIndividualEntity.getCityId())) {
                            resFlag = false;
                            userProvinceErrorMsg.append("<font size='4px' ><br>").append("第").append(buildingIndividualEntity.getRowNum() + 1).append("行").append("的数据省份不是用户所在地级市").append("</font><br>");
                            continue;
                        } else if (userMaxRole.equals("ph_county_role") && !sUser.getCountyId().equals(buildingIndividualEntity.getCountyId())) {
                            resFlag = false;
                            userProvinceErrorMsg.append("<font size='4px' ><br>").append("第").append(buildingIndividualEntity.getRowNum() + 1).append("行").append("的数据省份不是用户所在区县").append("</font><br>");
                            continue;
                        }
                        buildingIndividualEntity.setIsCountryLevel(0);
                    } else {
                        buildingIndividualEntity.setIsCountryLevel(1);
                    }
                    if (!resFlag) {
                        continue;
                    }
                    //设防情况
                    buildingIndividualEntity.setDefenceLevel(dictService.getKeyByDictCodeAndValue("sfqk", buildingIndividualEntity.getDefenceLevel()));
                    //结构类型一级
                    String structureType1 = buildingIndividualEntity.getStructureType1();
                    buildingIndividualEntity.setStructureType1(dictService.getKeyByDictCodeAndValue("jglxyj", structureType1));
                    if (structureType1.equals("砌体结构")) {
                        buildingIndividualEntity.setStructureType2(dictService.getKeyByDictCodeAndValue("qtjgej", buildingIndividualEntity.getStructureType2()));
                    }
                    if (structureType1.equals("钢筋混凝土结构")) {
                        buildingIndividualEntity.setStructureType2(dictService.getKeyByDictCodeAndValue("gjhntjgej", buildingIndividualEntity.getStructureType2()));
                    }
                    if (structureType1.equals("工业厂房")) {
                        buildingIndividualEntity.setStructureType2(dictService.getKeyByDictCodeAndValue("gycfej", buildingIndividualEntity.getStructureType2()));
                    }
                    String usage1 = buildingIndividualEntity.getUsage1();//房屋类型一级
                    buildingIndividualEntity.setUsage1(dictService.getKeyByDictCodeAndValue("fwytyj", usage1));
                    if (usage1.equals("第Ⅰ类")) {
                        buildingIndividualEntity.setUsage2(dictService.getKeyByDictCodeAndValue("dylej", buildingIndividualEntity.getUsage2()));
                    }
                    if (usage1.equals("第Ⅱ类")) {
                        buildingIndividualEntity.setUsage2(dictService.getKeyByDictCodeAndValue("delej", buildingIndividualEntity.getUsage2()));
                    }
                    if (usage1.equals("第Ⅲ类")) {
                        buildingIndividualEntity.setUsage2(dictService.getKeyByDictCodeAndValue("fwytsan", buildingIndividualEntity.getStructureType2()));
                    }
                    buildingIndividualEntity.setYear(dictService.getKeyByDictCodeAndValue("year", buildingIndividualEntity.getYear()));
                    buildingIndividualEntity.setFloors(dictService.getKeyByDictCodeAndValue("cengshu", buildingIndividualEntity.getFloors()));
                    buildingIndividualEntity.setDelFlag("0");
                    buildingIndividualEntity.setCreateUser(uploadUid);
                    buildingIndividualEntity.setCreateName(sUser.getUserName());
                    buildingIndividualEntity.setCreateTime(new Date());
                    buildingIndividualEntity.setGeom("POINT(" + buildingIndividualEntity.getLongitude() + " " + buildingIndividualEntity.getLatitude() + ")");
                    buildingIndividualEntity.setDataVersion(dataVersion);
                    list.add(buildingIndividualEntity);
                }
                if (!resFlag) {
                    map.put("res", false);
                    map.put("mess", userProvinceErrorMsg);
                    return map;
                }
                for (BuildingIndividualEntity buildingIndividualEntity : list) {
                    List<BuildingIndividualEntity> tList = buildingIndividualRepository.findByOnlyOneCondition(buildingIndividualEntity);
                    for (BuildingIndividualEntity individualEntity : tList) {
                        buildingIndividualRepository.delete(individualEntity.getId());
                    }
                    res = buildingIndividualRepository.save(buildingIndividualEntity);
                }
            }
        map.put("res", res);
        return map;
    }

    private String getUserMaxRole(String uploadUid) {
        List<SysUserRole> roleList = sysRoleCacheService.getRole(uploadUid);
        if (roleList == null) {
            throw new RuntimeException("未查询到用户角色信息!");
        }
        List<String> roleCodeList = roleList.stream().map(r -> r.getRoleCode()).collect(Collectors.toList());
        if (roleCodeList.contains("qh_gj_role") || roleCodeList.contains("fxqh_test_role")) {
            return "qh_gj_role";
        }
        if (roleCodeList.contains("qh_province_role")) {
            return "qh_province_role";
        }
        if (roleCodeList.contains("qh_city_role")) {
            return "qh_city_role";
        }
        if (roleCodeList.contains("ph_county_role")) {
            return "ph_county_role";
        }
        return null;
    }

    @Override
    public Map<String, Object> getPage(PageQueryParam queParams, int curPage, int pageSize) {
        Map<String, Object> page = buildingIndividualDataVersionRepository.getPage(queParams, curPage, pageSize);
        List<BuildingIndividualDataVersionVO> list = (List<BuildingIndividualDataVersionVO>) page.get("rows");
        list.forEach(item -> {
            String attachmentIds = item.getAttachmentIds();
            if (PlatformObjectUtils.isNotEmpty(attachmentIds)) {
                List<AttachmentInfoEntity> attachmentList = new LinkedList<>();
                for (String attachmentId : attachmentIds.split(",")) {
                    attachmentList.addAll(attachmentInfoService.queryFile(attachmentId));
                }
                item.setAttachmentList(attachmentList);

            }

            String dataFileIds = item.getDataFileIds();
            if (PlatformObjectUtils.isNotEmpty(dataFileIds)) {
                item.setDataFileList(attachmentInfoService.queryFile(item.getDataFileIds()));
            }


            SUser sUser = sUserCacheService.getSUser(item.getUploadUser());
            if (sUser != null) {
                item.setUploadUser(sUser.getUserName());
            }

            String id = "";
            if(StringUtils.isNotBlank(item.getDataRangeProvince())){
                id+=(item.getDataRangeProvince()+",");
            }
            if(StringUtils.isNotBlank(item.getDataRangeCity())){
                id+=(item.getDataRangeCity()+",");
            }
            if(StringUtils.isNotBlank(item.getDataRangeArea())){
                id+=(item.getDataRangeArea()+",");
            }
            if(id.endsWith(",")){
                id = id.substring(0,id.length()-1);
            }
            String province = "";
            String city = "";
            String area = "";
            if(StringUtils.isNotBlank(id)){
                String areaName = sysAreaService.getAreaNameByAreaId(id);
                if(StringUtils.isNotBlank(areaName)){
                    String[] split = areaName.split(",");
                    if(split.length==3){
                        area = split[2];
                        city = split[1];
                    }else if(split.length==2){
                        city = split[1];
                    }
                    province = split[0];
                }
            }
            item.setProvinceName(province);
            item.setCityName(city);
            item.setCountyName(area);


        });
        return page;
    }

    @Override
    public void delete(String id) {
        buildingIndividualDataVersionRepository.delete(id);
    }

    private void insertVersionData(BuildingIndividualDataVersion buildingIndividualDataVersion) {
        buildingIndividualDataVersion.setId(IdUtil.getSnowflakeNextIdStr());
        buildingIndividualDataVersion.setDelFlag(YNEnum.N.toString());
        Timestamp currTime = PlatformDateUtils.getCurrentTimestamp();
        buildingIndividualDataVersion.setUploadTime(currTime);
        String currUid = PlatformSessionContext.getUserID();
        //currUid="98加满";
        buildingIndividualDataVersion.setUploadUser(currUid);
        buildingIndividualDataVersion.setCreateTime(currTime);
        buildingIndividualDataVersion.setCreateUser(currUid);
//        buildingIndividualDataVersion.setUpdateTime(currTime);
//        buildingIndividualDataVersion.setUpdateUser(currUid);
        buildingIndividualDataVersion.setDataRange(this.buildDataRange(buildingIndividualDataVersion));
//        if (StringUtils.isBlank(buildingIndividualDataVersion.getUpdateDesc())) {
//            buildingIndividualDataVersion.setUpdateDesc("无");
//        }
        if ("全国".equals(buildingIndividualDataVersion.getDataRangeProvince())) {
            buildingIndividualDataVersion.setDataRangeProvince("");
            buildingIndividualDataVersion.setDataRangeCity("");
            buildingIndividualDataVersion.setDataRangeArea("");
        }
        if ("全部".equals(buildingIndividualDataVersion.getDataRangeCity())) {
            buildingIndividualDataVersion.setDataRangeCity("");
            buildingIndividualDataVersion.setDataRangeArea("");
        }
        if ("全部".equals(buildingIndividualDataVersion.getDataRangeArea())) {
            buildingIndividualDataVersion.setDataRangeArea("");
        }
        buildingIndividualDataVersionRepository.insert(buildingIndividualDataVersion);
    }

    /**
     * 构建数据范围文字显示
     *
     * @param buildingIndividualDataVersion 查询接口查询参数，数据版本原实体
     */
    private String buildDataRange(BuildingIndividualDataVersion buildingIndividualDataVersion) {
        if (buildingIndividualDataVersion.getDataRangeCountry() == 0) {
            return "-";
        }
        StringBuilder stringBuilder = new StringBuilder();
        String prefix = buildingIndividualDataVersion.getDataRangeCountry() == 1 ? "国家级" : "省级";
        if (StringUtils.isNotBlank(buildingIndividualDataVersion.getDataRangeProvince()) && !buildingIndividualDataVersion.getDataRangeProvince().equals("全国")) {
            String provinceName =
                    this.getAreaNameByAreaIdFromCache(
                            buildingIndividualDataVersion.getDataRangeProvince()); // 省
            if (StringUtils.isNotBlank(buildingIndividualDataVersion.getDataRangeCity()) && !"全国".equals(buildingIndividualDataVersion.getDataRangeCity())) {
                String cityName =
                        this.getAreaNameByAreaIdFromCache(
                                buildingIndividualDataVersion.getDataRangeCity()); // 市
                if (StringUtils.isNotBlank(buildingIndividualDataVersion.getDataRangeArea()) && !"全国".equals(buildingIndividualDataVersion.getDataRangeArea())) {
                    String areaName = "全部".equals(buildingIndividualDataVersion.getDataRangeArea()) ? "" :
                            this.getAreaNameByAreaIdFromCache(
                                    buildingIndividualDataVersion.getDataRangeArea()); // 区县
                    stringBuilder
                            .append(prefix)
                            .append("（")
                            .append(provinceName)
                            .append(cityName)
                            .append(areaName)
                            .append("）");
                } else {
                    stringBuilder
                            .append(prefix)
                            .append("（")
                            .append(provinceName)
                            .append(cityName)
                            .append("）");
                }
            } else {
                stringBuilder.append(prefix).append("（").append(provinceName).append("）");
            }
        } else {
            stringBuilder.append(prefix);
        }
        return stringBuilder.toString();
    }

    /**
     * 根据区域名称查询区域id
     *
     * @param areaId
     * @return
     */
    public String getAreaNameByAreaIdFromCache(String areaId) {
        if (StringUtils.isBlank(areaId)) {
            return null;
        }
        ValueOperations<String, String> ops = redisTemplate.opsForValue();
        String value = ops.get(FxfzConstants.CACHE_SYS_KEY + "areaMap");
        if (StringUtils.isNotBlank(value)) {
            JSONObject jsonObject = JSONObject.parseObject(value);
            String areaName = (String) jsonObject.get(areaId);
            if (StringUtils.isNotBlank(areaName)) {
                return areaName;
            } else {
                return sysAreaService.getAreaNameByAreaId(areaId);
            }
        } else {
            return sysAreaService.getAreaNameByAreaId(areaId);
        }
    }

    /**
     * 生成版本号
     *
     * <p>版本号规则：JZWDT+“数据范围代码”+“年月日”+“三位流水号” "数据范围编码：国家级数据01；省级数据02；市级数据03"
     *
     * @param dataRangeCode 数据范围 1国家级 2-省级 3-市级
     * @return
     */
    public synchronized String buildIndividualVersionCode(@NotNull int dataRangeCode) {
        ValueOperations<String, String> valueOperations = redisTemplate.opsForValue();
        String dataVersionCodeSerialNumber = valueOperations.get(DATA_VERSION_CODE_SERIAL_NUMBER_KEY);
        if (StringUtils.isBlank(dataVersionCodeSerialNumber)) {
            dataVersionCodeSerialNumber = "001";
        } else {
            StringBuilder stringBuilder = new StringBuilder();
            String t = String.valueOf(Integer.parseInt(dataVersionCodeSerialNumber) + 1);
            for (int i = t.length(); i < 3; i++) {
                stringBuilder.append("0");
            }
            dataVersionCodeSerialNumber = stringBuilder.append(t).toString();
        }
        redisTemplate
                .opsForValue()
                .set(DATA_VERSION_CODE_SERIAL_NUMBER_KEY, dataVersionCodeSerialNumber);
        redisTemplate.expireAt(
                DATA_VERSION_CODE_SERIAL_NUMBER_KEY,
                Date.from(LocalDateTime.of(LocalDate.now(), LocalTime.MAX).toInstant(ZoneOffset.of("+8"))));
        return DATA_VERSION_CODE_PREFIX
                + "0"
                + dataRangeCode
                + DateUtil.format(new Date(), "yyyyMMdd")
                + dataVersionCodeSerialNumber;
    }


    /**
     * 生成建筑物编号
     *
     * <p>建筑物编号规则：区县编号+6位有序数如000001、000002
     *
     * @param areaCode 区县code
     * @return
     */
    public synchronized String getBuildingCode(@NotNull String areaCode) {
        ValueOperations<String, String> valueOperations = redisTemplate.opsForValue();
        String buildCode = valueOperations.get(JZWBH_CODE_SERIAL_NUMBER_KEY+areaCode);
        if (StringUtils.isBlank(buildCode)) {
            buildCode = "000001";
        } else {
            StringBuilder stringBuilder = new StringBuilder();
            String t = String.valueOf(Integer.parseInt(buildCode) + 1);
            for (int i = t.length(); i < 6; i++) {
                stringBuilder.append("0");
            }
            buildCode = stringBuilder.append(t).toString();
        }
        redisTemplate
                .opsForValue()
                .set(JZWBH_CODE_SERIAL_NUMBER_KEY+areaCode, buildCode);
        return  areaCode + buildCode;
    }
}
